/**
 * @file filter
 * @author liaoxuezhi@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import * as React from 'react';
import {
  PureComponent,
  PropTypes
} from 'react';
import {render} from '../../renderer';
import * as cx from 'classnames';
import * as assign from 'object-assign';
import * as omit from 'lodash/omit';
import ReactSelect from 'react-select';
import * as find from 'lodash/find';
import {alert, confirm} from '../../../widgets/alert/alert';
import {Enhance as FormItem} from '../form-item';

@FormItem({
  type: 'forms',
  test: (path, config) => /(?:^|\/)form-item$/.test(path) && config.type === 'form' && config.forms,
  validateSchema: 'http://amis.baidu.com/schemas/form.json#/definitions/formItem'
})
export default class FormSubForms extends PureComponent {
  static propTypes = {
    className: PropTypes.string,
    formMode: PropTypes.string,
    formHorizontal: PropTypes.object,
    inputClassName: PropTypes.string,
    onRequestAction: PropTypes.func,
    forms: PropTypes.any.isRequired
  };

  static defaultProps = {
    value: '',
    inlineLabelClassName: '',
    typeField: 'type',
    labelField: 'title',
    addable: true,
    removable: true,
    maxLength: 0
  };

  values = {};

  constructor(props) {
    super(props);

    this.openSubForm = this.openSubForm.bind(this);
    this.addForm = this.addForm.bind(this);
    this.removeForm = this.removeForm.bind(this);
    this.handleFormResolved = this.handleFormResolved.bind(this);
    this.handleOptionChange = this.handleOptionChange.bind(this);
    this.close = this.close.bind(this);
    const forms = this.buildForms(props);

    this.state = {
      openIndex: -1,
      forms
    };
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;

    if (props.forms !== nextProps.forms) {
      this.setState({
        forms: this.buildForms(nextProps)
      });
    }
  }

  openSubForm(index = 0) {
    this.setState({
      openIndex: index
    });
    return false;
  }

  addForm() {
    let value = this.props.getValue() || [];

    if (!Array.isArray(value)) {
      value = [value];
    }

    const btnLabel = this.props.btnLabel;
    const labelField = this.props.labelField;

    value.push({
      [labelField]: ``
    });

    this.props.setValue(value);
  }

  removeForm(index) {
    const multiple = this.props.multiple;

    if (!multiple) {
      return this.props.setValue(null);
    }

    let value = this.props.getValue() || [];

    if (!Array.isArray(value)) {
      value = [value];
    }

    if (value[index]) {
      value.splice(index, 1);
    }

    this.props.setValue(value);
  }

  handleFormResolved(index, values) {
    let value = this.props.getValue() || [];

    if (!Array.isArray(value)) {
      value = [value];
    }

    value = value.concat();

    value.splice(index, 1, assign({}, value[index], values));
    this.props.setValue(value);
    this.close();
    this.values[index] = values;
  }

  handleOptionChange(option) {
    const {
      typeField,
      labelField,
      multiple
    } = this.props;
    const form = find(this.state.forms, item => item.value == option.value);

    if (multiple) {
      let value = this.props.getValue() || [];
      if (!Array.isArray(value)) {
        value = [value];
      }
      value = value.concat();

      if (!find(value, item => item[typeField] == option.value)) {
        value.push({
          [labelField]: form.label,
          [typeField]: form.value
        });
        this.props.setValue(value);
      }
    } else {
      const value = this.props.getValue();

      if (!value || value[typeField] != option.value) {
        this.props.setValue({
          [labelField]: form.label,
          [typeField]: form.value
        });
      }
    }
  }

  close() {
    this.setState({
      openIndex: -1
    });
  }

  buildForms(props) {
    let forms = props.forms;
    const labelField = props.labelField;
    const typeField = props.typeField;

    if (!forms) {
      return null;
    } else if (!Array.isArray(forms)) {
      forms = [forms];
    }

    return forms.map((form, index) => {
      const basicForm = omit(form, ['title', 'actions', 'name', 'label']);

      return {
        label: form[labelField] || form.label,
        value: form[typeField] || form.value || index,
        dialog: {
          title: form.title || props.form && props.form.title,
          name: form.value,
          size: form.size || props.size,
          body: assign({}, props.form, basicForm, {
            type: 'basic-form'
          })
        }
      }
    });
  }

  renderInput() {
    const {
      disabled,
      btnLabel,
      multiple,
      labelField,
      typeField,
      addable,
      removable,
      maxLength
    }= this.props;
    const forms = this.state.forms;
    let value = this.props.getValue();
    const doms = [];

    if (multiple) {
      const restForms = forms.concat();
      value = value || [];
      if (!Array.isArray(value)) {
        value = [value];
      }
      const length = value.length;
      value.forEach((value, key) => {
        const form = find(restForms, item => item.value == value[typeField]);
        restForms.splice(restForms.indexOf(form), 1);

        if (!value.hasOwnProperty(typeField) || !form) {
          doms.push(
            <button
              type="button"
              key={key}
              onClick={() => this.removeForm(key)}
              className="btn m-b-xs m-r-xs btn-danger btn-addon  btn-sm"
              disabled={disabled}
            >
              数据无效
              <i
                className="fa fa-times"
              />
            </button>
          );
        } else {
          doms.push(
            <button
              type="button"
              key={key}
              onClick={this.openSubForm.bind(this, key)}
              className="btn m-b-xs m-r-xs btn-info btn-addon btn-sm "
            >
              {value[labelField] || form.label || btnLabel}
              {disabled || !removable ? null : (
                <i
                  onClick={(e) => {
                    e.preventDefault();
                    e.stopPropagation();

                    confirm('确定要删除?').then(() => this.removeForm(key))
                    return false;
                  }}
                  className="fa fa-times"
                />
              )}
            </button>
          );
        }
      });

      addable && restForms.length && (!maxLength || length < maxLength) && doms.push(
        <ReactSelect
          key="options"
          placeholder="请选择"
          searchable={false}
          clearable={false}
          options={restForms}
          onChange={this.handleOptionChange}
          disabled={disabled}
        />
      );
    } else if (value) {
      const form = find(this.state.forms, item => item.value == value[typeField]);

      if (!value.hasOwnProperty(typeField) || !form) {
        doms.push(
          <button
            type="button"
            key="value"
            onClick={() => this.removeForm()}
            className="btn m-b-xs m-r-xs btn-danger btn-addon btn-sm "
            disabled={disabled}
          >
            数据无效
            <i
              className="fa fa-times"
            />
          </button>
        );
      } else {
        doms.push(
          <button
            type="button"
            key="value"
            onClick={this.openSubForm.bind(this, 0)}
            className="btn m-b-xs m-r-xs btn-info btn-addon btn-sm "
          >
            {value[labelField] || form[labelField] || btnLabel}
            {disabled ? null : (
              <i
                onClick={(e) => {
                  e.preventDefault();
                  e.stopPropagation();

                  confirm('确定要删除?').then(() => this.removeForm());
                  return false;
                }}
                className="fa fa-times"
              />
            )}
          </button>
        );
      }
    } else {
      doms.push(
        <ReactSelect
          key="options"
          placeholder="请选择"
          searchable={false}
          clearable={false}
          options={forms}
          onChange={this.handleOptionChange}
          disabled={disabled}
        />
      );
    }

    return doms;
  }

  render() {
    const {
      $path,
      locals,
      name,
      typeField,
      multiple,
      disabled,
      data
    } = this.props;

    let body = this.renderInput();


    const {openIndex, forms} = this.state;
    let value = this.props.getValue();

    if (multiple) {
      value = value || [];
      if (!Array.isArray(value)) {
        value = [value];
      }
      value = value && value[openIndex];
    }

    const form = value && find(forms, item => item.value == value[typeField]);

    return (
      <div>
        {body}
        {~openIndex && form ? render(`${$path}/form-dialog`, form.dialog, {
          data: assign({}, data, value || this.values[openIndex] || {}),
          name: `${name}-${form.dialog.name || 'sub-form'}`,
          locals,
          disabled,
          onClose: this.close,
          onResolved: this.handleFormResolved.bind(this, openIndex)
        }) : null}
      </div>
    );
  }
}
